
package fr.univ.projet.ihm;

import fr.univ.projet.*;
import fr.univ.projet.data.Base;
import fr.univ.projet.exception.GrilleException;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.util.ArrayList;
import java.util.List;
import javax.swing.*;


public class PanelGrille extends javax.swing.JPanel {

    private Jeu jeuEnCours;
    private JFrame parent;
    private JTextField txtMise = new JTextField();

    /**
     * Creates new form PanelGrille
     * 
     * @param parent Fenetre parent qui va contenir le panel
     * @param jeu Jeu choisi par le joueur pour faire une grille
     */
    public PanelGrille(JFrame parent, Jeu jeu) {

        this.jeuEnCours = jeu;
        this.parent = parent;
        
        Base base = Base.getInstance();
        Joueur jCo = base.getJoueurConnecte();

        this.setLayout(new GridBagLayout());
        int positionY = 0;

        // Placement du titre du Jeu
        JLabel titre = new JLabel("Grille pour le jeu : " + jeuEnCours.toString());
        GridBagConstraints gbcTitre = new GridBagConstraints();
        gbcTitre.gridx = 0;
        gbcTitre.gridy = positionY;
        gbcTitre.gridheight = 1;
        gbcTitre.gridwidth = 2;
        gbcTitre.fill = GridBagConstraints.HORIZONTAL;  
        gbcTitre.insets = new Insets(5, 5, 15, 5);

        this.add(titre, gbcTitre);
        positionY++;
        positionY++;

        Integer[] tabInt = new Integer[jeuEnCours.getNumeroMax() + 1];

        for (int i = jeuEnCours.getNumeroMin(); i <= jeuEnCours.getNumeroMax(); i++) {
            tabInt[i] = i;
        }

        // Création et placement des champs pour la saisie des numéros en fonction des paramètre du jeu
        for (int i = 1; i <= jeuEnCours.getNbreNumero(); i++) {
            JLabel label = new JLabel("Numéro " + i);

            JComboBox combo = new JComboBox(tabInt);
            combo.setName("comboNum" + i);

            GridBagConstraints gbcLabel = new GridBagConstraints();
            gbcLabel.gridx = 0;
            gbcLabel.gridy = positionY;
            gbcLabel.gridheight = 1;
            gbcLabel.gridwidth = GridBagConstraints.RELATIVE;

            GridBagConstraints gbcField = new GridBagConstraints();
            gbcField.gridx = 1;
            gbcField.gridy = positionY;
            gbcField.gridheight = 1;
            gbcField.gridwidth = GridBagConstraints.REMAINDER;

            this.add(label, gbcLabel);
            this.add(combo, gbcField);

            positionY++;

        }

        // Vérifie dans les règle du jeu si il y a un numéro chance à gérer
        if (jeuEnCours.getNbreNumeroChance() > 0) {
            Integer[] tabChance = new Integer[jeuEnCours.getNumeroChanceMax() + 1];

            for (int i = jeuEnCours.getNumeroChanceMin(); i <= jeuEnCours.getNumeroChanceMax(); i++) {
                tabChance[i] = i;
            }

            // Il y a une case supplémentaire pour le numéro chance
            JLabel label = new JLabel("Chance ");

            JComboBox combo = new JComboBox(tabChance);
            combo.setName("comboChance");

            GridBagConstraints gbcLabel = new GridBagConstraints();
            gbcLabel.gridx = 0;
            gbcLabel.gridy = positionY;
            gbcLabel.gridheight = 1;
            gbcLabel.gridwidth = GridBagConstraints.RELATIVE;

            GridBagConstraints gbcField = new GridBagConstraints();
            gbcField.gridx = 1;
            gbcField.gridy = positionY;
            gbcField.gridheight = 1;
            gbcField.gridwidth = GridBagConstraints.REMAINDER;

            this.add(label, gbcLabel);
            this.add(combo, gbcField);

            positionY++;
        }

        // Ajout du champs pour indiquer la mise
        JLabel lblMise = new JLabel("Mise : ");
        GridBagConstraints gbcLblMise = new GridBagConstraints();
        gbcLblMise.gridx = 0;
        gbcLblMise.gridy = positionY;
        gbcLblMise.gridheight = 1;
        gbcLblMise.gridwidth = 1;
        gbcLblMise.insets = new Insets(15, 0, 15, 0);
        this.add(lblMise, gbcLblMise);
        
        txtMise.setName("txtMise");
        txtMise.setPreferredSize(new Dimension(100, 30));
                
        GridBagConstraints gbcTxtMise = new GridBagConstraints();
        gbcTxtMise.gridx = 1;
        gbcTxtMise.gridy = positionY;
        gbcTxtMise.gridheight = 1;
        gbcTxtMise.gridwidth = 1;
        gbcTxtMise.insets = new Insets(15, 0, 15, 0);

        this.add(txtMise, gbcTxtMise);
        positionY++;
        
        // Ajouter le bouton de validation
        JButton btnValider = new JButton("Valider");
        btnValider.setName("btnValider");
        btnValider.addActionListener(new java.awt.event.ActionListener() {

            @Override
            public void actionPerformed(java.awt.event.ActionEvent evt) {
                btnValiderActionPerformed(evt);
            }
        });

        // Ajout du bouton "Valider"
        GridBagConstraints gbcBtnValid = new GridBagConstraints();
        gbcBtnValid.gridx = 0;
        gbcBtnValid.gridy = positionY;
        gbcBtnValid.gridheight = 1;
        gbcBtnValid.gridwidth = 1;
        gbcBtnValid.insets = new Insets(15, 0, 15, 0);

        this.add(btnValider, gbcBtnValid);
      
        // Ajouter le bouton de validation
        JButton btnRetour = new JButton("Retour");
        btnRetour.setName("btnRetour");
        btnRetour.addActionListener(new ActionListener() {

            @Override
            public void actionPerformed(ActionEvent e) {
                btnRetourActionPerformed(e);
            }

        });
        
        GridBagConstraints gbcBtnRetour = new GridBagConstraints();
        gbcBtnRetour.gridx = 1;
        gbcBtnRetour.gridy = positionY;
        gbcBtnRetour.gridheight = 1;
        gbcBtnRetour.gridwidth = 1;
        gbcBtnRetour.insets = new Insets(15, 0, 15, 0);

        this.add(btnRetour, gbcBtnRetour);
        
        setSize(parent.getWidth(), parent.getHeight());
        setVisible(true);
    }

    /**
     * Retourne à la page du compte du joueur sans enregistrer de grille
     * 
     * @param e 
     */
    private void btnRetourActionPerformed(ActionEvent e) 
    {
       PanelGrille.this.parent.setContentPane(new PanelJeux(PanelGrille.this.parent));
       PanelGrille.this.parent.pack();
    }
    
    /**
     * Action permettant d'enregistrer une grille pour un jeu
     * @param e 
     */
    private void btnValiderActionPerformed(ActionEvent e) {
        // Récupère l'ensemble des composants du panel
        Component[] tabC = PanelGrille.this.getComponents();
        List<Numero> lstNumJoue = new ArrayList<Numero>();
        boolean error = false;
        List<String> msgErr = new ArrayList<String>();
        for (Component c : tabC) {
            // Test si le composant en cours est un composant dont le nom contient "combo"
            // Si c'est le cas on doit le traiter car c'est un champs "Numero"
            if (c.getName() != null && c.getName().contains("combo")) {
                if (c.getClass().equals(JComboBox.class)) {
                    JComboBox cb = (JComboBox) c;
                    // Test si une valeur a été selectionné, si c'est pas le cas on affichera une erreur
                    if (cb.getSelectedItem() == null) {
                        if (cb.getName().equals("comboChance")) {
                            msgErr.add("Chance non sélectionné !");
                        } else {
                            msgErr.add("Numéro non sélectionné !");
                        }

                        error = true;
                    } else {
                        // Test si c'est un numéro simple ou un numéro chance avant de l'ajouter dans la liste des numéros joués
                        if (cb.getName().equals("comboChance")) {
                            Numero chance = new Chance(Integer.parseInt(cb.getSelectedItem().toString()));
                            lstNumJoue.add(chance);
                        } else {
                            // C'est un numéro simple donc on doit vérifier que la valeur n'a pas déjà été sélectionnée
                            Numero numero = new Numero(Integer.parseInt(cb.getSelectedItem().toString()));
                            if (!doublon(numero.getValeur(), lstNumJoue)) {
                                lstNumJoue.add(numero);
                            } else {
                                error = true;
                                msgErr.add("Tous les numéros doivent être différents !");
                            }
                        }
                    }
                }
            }
        }

        // traitement de la mise
        String mise = PanelGrille.this.txtMise.getText();
        float miseF = 0;
        if (mise.isEmpty()) {
            // Erreur
            error = true;
            msgErr.add("La mise est obligatoire");
        } 
        else  
        {
            try {
                // On cast la valeur récupérer dans le champs mise pour être sur que l'on a bien un numérique
                miseF = Float.parseFloat(mise);
            } catch (NumberFormatException ex) {
                error = true;
                msgErr.add("La mise doit être un numérique !");
            }
            if ( miseF == 0 )
            {
                error = true;
                msgErr.add("La mise doit être supérieure à 0 !");
            }
        }

        if (error) {
            // Il y a des erreurs donc on affiche l'ensemble des erreurs trouvées
            StringBuilder sb = new StringBuilder();
            for (String msg : msgErr) {
                sb.append(msg);
                sb.append("\n");
            }
            JOptionPane.showMessageDialog(PanelGrille.this, sb.toString(), "Erreur", JOptionPane.ERROR_MESSAGE);
        } else {
            // Pas d'erreur donc on "enregistre" la grille
            Base base = Base.getInstance();
            Joueur jCo = base.getJoueurConnecte();

            int numGrille = base.getNumeroGrille();

            Grille g = jCo.ajouterUneGrille(numGrille, PanelGrille.this.jeuEnCours);
            try {
                jCo.ajouterLesNumerosChoisis(lstNumJoue, g);
                jCo.ajouterMise(miseF, g);
            } catch (GrilleException ex) {
                // Il y a eut un problème lors de l'enregistrement de la grille. 
                // On affiche l'erreur qui a été trouvé par la méthode d'enregistrement
                System.err.println(ex.getMessage());
                JOptionPane.showMessageDialog(PanelGrille.this, ex.getMessage(), "Erreur", JOptionPane.ERROR_MESSAGE);
                error = true;
            }

            if (!error) {
                // Si aucune erreur trouvé alors on retourne sur le compte joueur
                PanelGrille.this.parent.setContentPane(new PanelJeux(PanelGrille.this.parent));
                PanelGrille.this.parent.pack();
            }
        }

    }
    
    /**
     * Test si un numéro existe déjà dans une liste
     * 
     * @param pNumero numéro à tester
     * @param laListe liste contenant les numéros déjà sélectionnés
     * 
     * @return vrai si le numéro existe deja dans la liste, faux sinon
     */
    private boolean doublon(int pNumero, List<Numero> laListe) {
        boolean trouve = false;
        //variable d'itération
        int i = 0;
        
        while (i < laListe.size() && !trouve) {

            Numero num = (Numero) laListe.get(i);
            
            // on test si la valeur est egale entre le numéro en parametre et ceux de la liste
            // et si le numéro n'est pas de type Chance
            if (num.getValeur() == pNumero && !num.getClass().equals(Chance.class))
            {
                trouve = true;
            }

            i++;

        }
        return trouve;
    }
   
    /**
     * This method is called from within the constructor to initialize the form.
     * WARNING: Do NOT modify this code. The content of this method is always
     * regenerated by the Form Editor.
     */
    @SuppressWarnings("unchecked")
    // <editor-fold defaultstate="collapsed" desc="Generated Code">//GEN-BEGIN:initComponents
    private void initComponents() {

        javax.swing.GroupLayout layout = new javax.swing.GroupLayout(this);
        this.setLayout(layout);
        layout.setHorizontalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 400, Short.MAX_VALUE)
        );
        layout.setVerticalGroup(
            layout.createParallelGroup(javax.swing.GroupLayout.Alignment.LEADING)
            .addGap(0, 300, Short.MAX_VALUE)
        );
    }// </editor-fold>//GEN-END:initComponents
    // Variables declaration - do not modify//GEN-BEGIN:variables
    // End of variables declaration//GEN-END:variables
}
